﻿using mozhi.smarterp.Finance.Accounts;
using mozhi.smarterp.Finance.Accounts.Repository;
using mozhi.smarterp.Finance.Accounts.Services;
using mozhi.smarterp.Finance.Basedatas.Repository;
using mozhi.smarterp.Finance.Basedatas.Services;
using mozhi.smarterp.Finance.Finances.Repository;
using mozhi.smarterp.Finance.Finances.Services;
using mozhi.smarterp.Finance.Querys;
using mozhi.smarterp.Finance.Reports.Repository;
using Mozhi.Abp.Core.Extensions;
using Mozhi.Abp.Domain.BasicData;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;

namespace mozhi.smarterp.Finance.Reports
{
    public class CashflowStatementReportAppService : FinancialReportAppService, ICashflowStatementReportAppService
    {
        private IFinancialReportItemRepository _financialReportItemRepository;
        private IIncomeStatementReportAppService _incomeStatementReportAppService;

        public CashflowStatementReportAppService(IAccountRepository accountRepository, IDimensionGroupValueRepository dimensionGroupValueRepository, ICurrencyRepository currencyRepository,
            ISettlementRepository settlementRepository, IAccountBalanceRepository accountBalanceRepository, AccountBalanceManager accountBalanceManager,
            DimensionGroupValueManager dimensionGroupValueManager, IOrganizationRepository organizationRepository, IEndPeriodProcessResultRepository endPeriodProcessResultRepository,
            IJournalRepository journalRepository, JournalManager journalManager, IFinancialReportItemRepository financialReportItemRepository, IIncomeStatementReportAppService incomeStatementReportAppService) :
            base(accountRepository, dimensionGroupValueRepository, currencyRepository, settlementRepository, accountBalanceRepository, accountBalanceManager,
                dimensionGroupValueManager, organizationRepository, endPeriodProcessResultRepository, journalRepository, journalManager)
        {
            _financialReportItemRepository = financialReportItemRepository;
            _incomeStatementReportAppService = incomeStatementReportAppService;
        }

        public async Task<List<CashflowStatementReportDto>> GetDataAsync(CashflowStatementReportQuery query)
        {
            var result = new List<CashflowStatementReportDto>();

            if (query.StartPeriod <= 0)
                return result;

            query.EndPeriod = query.DataType == 1 ? query.StartPeriod : query.EndPeriod;

            if (query.EndPeriod == 0)
                throw new UserFriendlyException("结束期间不能为空", "100000");

            if (query.StartPeriod.ToLastDayDateTime().Year != query.EndPeriod.ToLastDayDateTime().Year)
                throw new UserFriendlyException("不允许跨年查询", "100000");

            var balances = await GetAccountBalancesAsync(new ReportQueryBase() { StartPeriod = query.StartPeriod , EndPeriod = query.EndPeriod , IncludeCurrency=false , IncludeDimension=false , IncludeUnApproveJournal=query.IncludeUnApproveJournal });


            result = await HandleCashFlowStatement(query ,balances);

            return result;
        }


        #region
        /// <summary>
        /// 处理现金流量表数据
        /// </summary>
        /// <param name="filter"></param>
        /// <param name="balances"></param>
        /// <param name="accounts"></param>
        /// <returns></returns>
        private async Task<List<CashflowStatementReportDto>> HandleCashFlowStatement(CashflowStatementReportQuery filter, List<AccountBalance> balances)
        {
            //var reportItems = await _financialReportItemRepository.FindAsync(new FinancialReportItemQuery() { ReportType = Enums.FinancialReportType.StatementOfCashFlow });

            //var result = new List<CashflowStatementReportDto>();

            //if (reportItems.Count == 0)
            //    return result;

            //var accounts = await _accountRepository.FindAsync(new AccountQuery());

            ////不要破坏原始数据，后面还需要用到
            //var currentPeriodBalances = balances.Where(x => x.Period >= filter.StartPeriod && x.Period <= filter.EndPeriod).ToList();


            ////去掉结转损益凭证的金额
            //var firstPeriod = filter.StartPeriod.ToLastDayDateTime().Year * 100 + 1;
            //var lastPeriod = filter.EndPeriod.ToLastDayDateTime().Year * 100 + 1; ;

            //await ExcludeProfitLossJournal(accounts, firstPeriod, filter.EndPeriod, currentPeriodBalances, filter.IncludeUnApproveJournal);

            //var normalReportItems = reportItems.Where(x => x.AssociateCode != "additional").ToList();

            //var outputNormalReportItems = ObjectMapper.Map<List<FinancialReportItem>, List<FinancialReportItemDto>>(normalReportItems);

            //foreach (var reportItem in normalReportItems)
            //{
            //    var outputResult = new CashflowStatementReportDto();

            //    outputResult.ReportItemId = reportItem.Id;
            //    outputResult.ReportItemName = reportItem.Name;
            //    outputResult.Number = reportItem.Number;

            //    var outputMatchReportItem = outputNormalReportItems.FirstOrDefault(x => x.Id == reportItem.Id);
            //    //本期数
            //    outputResult.CurrentPeriodAmount = await GetReportItemAmount(1, outputMatchReportItem, accounts, currentPeriodBalances, outputNormalReportItems, filter.StartPeriod, filter.EndPeriod);

            //    result.Add(outputResult);
            //}

            ////附加报表项，这个只有企业会计准则会有
            //var additionalReportItems = reportItems.Where(x => x.AssociateCode == "additional").ToList();

            //if (additionalReportItems.Count > 0)
            //{
            //    //增加一个附加的行
            //    var outputResult = new CashflowStatementReportDto();

            //    outputResult.ReportItemId = null;
            //    outputResult.ReportItemName = "附加";
            //    outputResult.Number = "";
            //    //本期数
            //    outputResult.CurrentPeriodAmount = null;

            //    result.Add(outputResult);
            //}

            //var outputAdditionalReportItems = ObjectMapper.Map<List<FinancialReportItem>, List<FinancialReportItemDto>>(additionalReportItems);

            //var totalReportItems = new List<FinancialReportItemDto>();

            //totalReportItems.AddRange(outputNormalReportItems);
            //totalReportItems.AddRange(outputAdditionalReportItems);

            //foreach (var reportItem in additionalReportItems)
            //{
            //    var outputResult = new CashflowStatementReportDto();

            //    outputResult.ReportItemId = reportItem.Id;
            //    outputResult.ReportItemName = reportItem.Name;
            //    outputResult.Number = reportItem.Number;

            //    var outputMatchReportItem = outputAdditionalReportItems.FirstOrDefault(x => x.Id == reportItem.Id);

            //    if (reportItem.Code == "1_103_40")
            //        outputResult.CurrentPeriodAmount = await GetCashFlowStatementNetProfit(filter, balances, accounts ,(await GetOrganizationAsync()));  //净利润需要单独需要取利润表的数据
            //    else
            //        outputResult.CurrentPeriodAmount = await GetReportItemAmount(1, outputMatchReportItem, accounts, currentPeriodBalances, totalReportItems); //本期数

            //    result.Add(outputResult);
            //}
            //return result;
            throw new NotImplementedException();
        }


        private async Task<decimal?> GetCashFlowStatementNetProfit(CashflowStatementReportQuery filter, List<AccountBalance> balances, List<Account> accounts , Organization organization)
        {
            var reportItemCode = organization.AccountingStandard ==  (int)Enums.AccountingStandardType.BusinessEnterprises ? "1_101_32" : "2_101_32";

            var matchReportItem = (await _financialReportItemRepository.FindAsync(new FinancialReportItemQuery() { Code = reportItemCode})).FirstOrDefault();

            if (matchReportItem == null)
                return 0;

            var incomeStatementQuery = new IncomeStatementReportQuery() { DateType = filter.DataType, StartPeriod = filter.StartPeriod, EndPeriod = filter.EndPeriod, IncludeUnApproveJournal = filter.IncludeUnApproveJournal };

            var incomeStatementReports = await _incomeStatementReportAppService.HandleIncomeStatement(incomeStatementQuery, balances);

            if (incomeStatementReports == null || incomeStatementReports.Count == 0)
                return 0;

            var matchIncomeReport = incomeStatementReports.FirstOrDefault(x => x.ReportItemId == matchReportItem.Id);

            var netProfit = matchIncomeReport == null ? null : matchIncomeReport.CurrentPeriodAmount;

            return netProfit;

        }
        #endregion
    }
}
